﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Hyt.Core.Interceptors;
using Hyt.Core;
using Hyt.Core.Data;
using Hyt.Passport.QueryModels;
using Hyt.Passport.Models;
using Hyt.Passport.Repositories;

namespace Hyt.Passport.Service
{
    public class DepartmentService 
    {
        public IDepartmentRepository Repository { get; set; }

        public virtual void CreateByParent(string name,string parentcode=null)
        {
            if (!string.IsNullOrWhiteSpace(parentcode))
            {
                var parent = Get(parentcode);
                Guard.MustExist(parent,"父级部门");
            }
            var code = GetNewChildCode(parentcode);
            Department model = new Department { Code = code, Name = name };
            Create(model);
        }

        public virtual Department Create(Department model)
        {
            Guard.Check(model).PleaseInput(t => t.Name,t=>t.Code);
            model.Name = model.Name.Trim().ToLower();
            model.Code = model.Code.Trim().ToLower();
            if (model.Code.Length < Department.OnGradeCodeLength || model.Code.Length % Department.OnGradeCodeLength != 0)
            {
                Guard.Throw("编码不正确");
            }
            if (GetAll().Any(t => t.Code == model.Code))
            {
                Guard.Throw("编码已存在");
            }
            if (model.Code.Length > Department.OnGradeCodeLength)
            {
                var parentcode = model.Code.Substring(0, model.Code.Length - Department.OnGradeCodeLength);
                if (GetAll().All(t => t.Code != parentcode))
                {
                    Guard.Throw("编码不正确,未找到父级部门");
                }
                if (GetAll().Any(t => t.Code.StartsWith(parentcode) && t.Name == model.Name))
                {
                    Guard.Throw("已存在相同名称部门");
                }
            }
            else
            {
                if (GetAll().Any(t => t.Code.Length== Department.OnGradeCodeLength && t.Name == model.Name))
                {
                    Guard.Throw("已存在相同名称部门");
                }
            }

            return Repository.AddDepartment(model);
        }

        public void ModifyName(Department model)
        {
            Guard.CheckArg(model, "model");
            Guard.DontNull(model.Name,"部门名称");
            var dprt = Get(model.Id);
            Guard.MustExist(dprt,"部门");

            if (dprt.Code.Length > Department.OnGradeCodeLength)
            {
                var parentcode = dprt.Code.Substring(0, dprt.Code.Length - Department.OnGradeCodeLength);
                if (GetAll().Any(t => t.Code.StartsWith(parentcode) && t.Name == model.Name&&t.Id!=model.Id))
                {
                    Guard.Throw("已存在相同名称部门");
                }
            }
            else
            {
                if (GetAll().Any(t => t.Code.Length == Department.OnGradeCodeLength && t.Name == model.Name && t.Id != model.Id))
                {
                    Guard.Throw("已存在相同名称部门");
                }
            }
            dprt.Name = model.Name;
            Repository.UpdateDepartment(dprt);
        }

        public virtual IQueryable<Department> GetAll(QueryOption<Department> option = null)
        {
            return Repository.GetDepartments(option);
        }

        /// <summary>
        /// 获取本身和子部门列表
        /// </summary>
        /// <returns></returns>
        public virtual IQueryable<Department> GetSelfAndChild(Guid id)
        {
            var depts = GetAll().Where(t=>t.Id==id);
            if (!depts.Any())
            {
                return depts;
            }
            var dept = depts.First();
            var result = GetAll().Where(t => t.Code.StartsWith(dept.Code));
            return result;
        }

        public virtual Department Get(Guid id)
        {
            return Repository.GetDepartments().FirstOrDefault(t => t.Id == id);
        }

        public virtual Department Get(String code)
        {
            return Repository.GetDepartments().FirstOrDefault(t => t.Code == code);
        }
        
        public virtual IPagedQueryable<Department> GetDepartments(DepartmentQueryModel qo)
        {
            IPagedQueryable<Department> result = new PagedQueryable<Department>();
            var all = GetAll(qo.QueryOption.Cast<Department>());
            if (!string.IsNullOrWhiteSpace(qo.Name))
            {
                all = all.Where(t => t.Name.Contains(qo.Name));
            }
            result.Total = all.Count();
            if (!string.IsNullOrWhiteSpace(qo.OrderBy))
            {
                all = all.SortBy(qo.OrderBy, qo.OrderType);
                all = all.PageBy(qo.PageIndex, qo.PageSize);
            }
            result.Data = all;
            result.PageIndex = qo.PageIndex;
            result.PageSize = qo.PageSize;
            return result;

        }

        public virtual string GetNewChildCode(string parentcode)
        {
            int max = 0;
            if (!string.IsNullOrWhiteSpace(parentcode))
            {
                var allchild = GetAll().Where(t => t.Code.StartsWith(parentcode) && t.Code != parentcode);
                foreach (var child in allchild)
                {
                    var code = int.Parse(child.Code.Substring(parentcode.Length));
                    max = Math.Max(max, code);
                }
            }
            else
            {
                var allchild = GetAll().Where(t => t.Code.Length==Department.OnGradeCodeLength);
                foreach (var child in allchild)
                {
                    var code = int.Parse(child.Code);
                    max = Math.Max(max, code);
                }
            }
            return parentcode + (max + 1).ToString().PadLeft(Department.OnGradeCodeLength, '0'); 
        }

        public virtual void Remove(Guid id)
        {
            Department p = Get(id);
            Guard.MustExist(p, "部门");
            if (p.Administrators.Any())
            {
                Guard.Throw("不能删除存在用户的部门");
            }
            if (p.Positions.Any())
            {
                Guard.Throw("不能删除存在职位的部门");
            }
            Repository.RemoveDepartment(p);
        }
    }
}
